package limedia.sdk.api.realtime;

import com.limedia.explorer.enums.Enums.ClientNo;
import com.limedia.explorer.enums.Enums.TSEDecodeType;
import com.limedia.explorer.enums.Enums.TSERTPlayState;
import com.limedia.explorer.interfaces.TSIPlayerStateListener;

import android.os.Handler;
import android.util.Log;
import android.view.Surface;

/**
 * real time player
 * 
 * @author ThunderSoft
 *
 */
public class TSRealTimePlayer {

	private static final String TAG = "TSRealTimePlayer";
//	private static TSRealTimePlayer mRealTimePlayer = null;

	private Surface mSurface = null;
	private TSEDecodeType decodeType = null;
	private TSVideoDecoder videoDecoder = null;
//	private TSAudioDecoder audioDecoder = null;
	private TSRTSPNative mTsrtpNative = null;
	private TSPlayerDTO mPlayerDTO = null;
	private TSIPlayerStateListener mListener = null;

	private static final int PLAYER_ONPLAY = 0;
	private static final int PLAYER_ONSTOP = 1;
	private static final int PLAYER_ONPREPARECOMPLETE = 2;
	private static final int PLAYER_ONERROR = 3;
	private String mRtspUrl = null;
//	private Handler mHandler = null;

	private boolean isPlaying = false;
	private boolean isPrepared = false;
	
	private ClientNo mClientNo = null;

	/**
	 * get TSRealTimePlayer instance
	 * 
	 * @return TSRealTimePlayer instance
	 */
//	public static synchronized TSRealTimePlayer getInstance(String rtspUrl, Handler handler) {
//		if (null == mRealTimePlayer) {
//			mRealTimePlayer = new TSRealTimePlayer();
//			mRtspUrl=rtspUrl;
//			mHandler=handler;
//		}
//		Log.i(TAG, "getInstance");
//		return mRealTimePlayer;
//	}

	public TSRealTimePlayer(String rtspUrl, TSPlayerDTO playerDTO) {
		super();
		Log.i(TAG, "constructor");
		
		this.mRtspUrl = rtspUrl;
//		this.mHandler = handler;
		this.mPlayerDTO = playerDTO;
	}

	
	
	public void setClientNo(ClientNo clientNo) {
		this.mClientNo = clientNo;
	}



	/**
	 * set decode type
	 * 
	 * @param decodeType
	 *            TSEDecodeType
	 */
	public void setDecodeType(TSEDecodeType decodeType) {
		this.decodeType = decodeType;
	}

	/**
	 * set surface
	 * 
	 * @param surface
	 *            Surface
	 */
	public void setSurface(Surface surface) {
		this.mSurface = surface;
	}

	/**
	 * set player listener
	 * 
	 * @param listener
	 *            TSIPlayerStateListener
	 */
	public void setPlayerListener(TSIPlayerStateListener listener) {
		this.mListener = listener;
	}

	/**
	 * prepare for realtime player
	 */
	public void prepare() {
		if (this.isPlaying) {
			return;
		}
		
		if(null == this.mPlayerDTO) {
			this.mPlayerDTO = new TSPlayerDTO();
		}
		
		// TODO
		if (null == this.mTsrtpNative) {
			this.mTsrtpNative = TSRTSPNative.getInstance();
			switch (this.mClientNo) {
			case Client_ONE:
				this.mTsrtpNative.initClient1(
						this.mRtspUrl, this.mPlayerDTO.getPcmQueueForVideo(), this.mPlayerDTO.getPcmQueueForAudio());
				break;
			case Client_TWO:
				this.mTsrtpNative.initClient2(
						this.mRtspUrl, this.mPlayerDTO.getPcmQueueForVideo(), this.mPlayerDTO.getPcmQueueForAudio());
				break;
			case Client_THREE:
				this.mTsrtpNative.initClient3(
						this.mRtspUrl, this.mPlayerDTO.getPcmQueueForVideo(), this.mPlayerDTO.getPcmQueueForAudio());
				break;
			default:
				break;
			}
		}

		if (null == this.videoDecoder) {
			if (null == this.mSurface) {
				this.performPlayListener(PLAYER_ONERROR, TSERTPlayState.RT_PLAY_STATE_NO_SURFACE);
				Log.i(TAG, "prepare: surface is null");
				return;
			}
			this.videoDecoder = new TSVideoDecoder(this.mPlayerDTO, this.mSurface, this.mPlayerDTO.getPcmQueueForVideo(),
					new TSVideoDecoder.OnFrameAvailabkeListener() {
						@Override
						public void onFrameAvailable(long timestamp, int index) {
							videoDecoder.render(index);
						}
					});
		}
//		if (null == this.audioDecoder) {
//			this.audioDecoder = new TSAudioDecoder(this.mPlayerDTO.getPcmQueueForAudio());
//		}
		if (null == this.decodeType) {
			this.decodeType = this.mPlayerDTO.getDecodeType();
		}

		TSERTPlayState state = this.videoDecoder.initDecoder(this.decodeType);
//		this.audioDecoder.initDecoder();
		if (state != TSERTPlayState.RT_PLAY_STATE_SUCCESS) {
			this.performPlayListener(PLAYER_ONERROR, state);
		}

		// TODO TEST CODE
		// TSCameraController.getInstance().getSPSAndPPS(this.spsAndPPSCallBack);
		this.isPrepared = true;
		this.performPlayListener(PLAYER_ONPREPARECOMPLETE, null);
		Log.i(TAG, "prepare end");
	}

	/**
	 * start realtime player
	 */
	public void start() {
		if (this.isPrepared && !this.isPlaying) {
			this.mTsrtpNative.start(this.mClientNo);
			this.videoDecoder.start();
//			this.audioDecoder.start();
			this.isPlaying = true;
			this.performPlayListener(PLAYER_ONPLAY, null);
			Log.i(TAG, "start");
		}
	}

	/**
	 * stop realtime player
	 */
	public void stop() {
		if (this.isPlaying) {
			switch (this.mClientNo) {
			case Client_ONE:
				this.mTsrtpNative.stop(0);
				break;
			case Client_TWO:
				this.mTsrtpNative.stop(1);
				break;
			case Client_THREE:
				this.mTsrtpNative.stop(2);
				break;
			default:
				break;
			}
			this.videoDecoder.stop();
//			this.audioDecoder.stop();
			this.isPlaying = false;
			this.isPrepared = false;
			this.performPlayListener(PLAYER_ONSTOP, null);
			Log.i(TAG, "stop");
		}
	}

	/**
	 * release realtime player
	 */
	public void release() {
		if (this.isPlaying) {
			this.stop();
		}
		this.mTsrtpNative = null;
		if (null != this.videoDecoder) {
			this.videoDecoder.release();
			this.videoDecoder = null;
		}
//		if (null != this.audioDecoder) {
//			this.audioDecoder.release();
//			this.audioDecoder = null;
//		}
		this.isPlaying = false;
		this.isPrepared = false;
		this.decodeType = null;
		this.mSurface = null;
		this.mListener = null;
//		mRealTimePlayer = null;
		Log.i(TAG, "release");
	}

	/**
	 * realtime player is playing or not
	 * 
	 * @return
	 */
	public boolean isPlaying() {
		return this.isPlaying;

	}

	private void performPlayListener(int playFunc, TSERTPlayState state) {
		if (mListener != null) {
			switch (playFunc) {
			case PLAYER_ONPLAY:
				this.mListener.onPlay();
				break;
			case PLAYER_ONPREPARECOMPLETE:
				this.mListener.onPrepareComplete();
				break;
			case PLAYER_ONSTOP:
				this.mListener.onStop();
				break;
			case PLAYER_ONERROR:
				this.mListener.onError(state);
				break;
			default:
				break;
			}
		}
	}



	public void startUpload() {
		if (this.isPlaying) {
			switch (this.mClientNo) {
			case Client_ONE:
				this.mTsrtpNative.native_forward(1);
				break;
			case Client_TWO:
				this.mTsrtpNative.native_forward(2);
				break;
			case Client_THREE:
				this.mTsrtpNative.native_forward(3);
				break;
			default:
				break;
			}
			Log.i(TAG, "startUpload " + mClientNo);
		}
	}



	public void stopUpload() {
		// TODO Auto-generated method stub
	}
	
}
